﻿namespace AsyncLog
{
	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Threading.Tasks;
	using System.Windows.Forms;

	using AsyncLog.Properties;
	using PugLib;
	using PugLib.UI;

	public sealed partial class AsyncLogDemo : TaskForm, IListener<NewMessage>
	{
		private readonly AsyncLogController _controller;
		private Object _rightClickItem;

		public AsyncLogDemo()
		{
			InitializeComponent();
			_controller = new AsyncLogController(this);
			_controller.EventAggregator.Subscribe(this);
			kryptonListBox1.ListBox.MouseUp += ListBoxMouseUp;

			spark.PixelsPerElement = 1;
		}

		internal AsyncLogController Controller
		{
			get { return _controller; }
		}

		#region IListener<NewMessage> Members

		public void Receive(NewMessage receivedMessage)
		{
			if (receivedMessage == null)
			{
				throw new ArgumentNullException("receivedMessage");
			}
			WriteLogEntry(receivedMessage.Entry);
			BuildSparkline();
		}

		public void StopListening()
		{
			_controller.EventAggregator.Unsubscribe(this);
		}

		#endregion

		private void ListBoxMouseUp(Object sender, MouseEventArgs e)
		{
			if (e.Button == System.Windows.Forms.MouseButtons.Right)
			{
				int index = kryptonListBox1.ListBox.IndexFromPoint(e.X, e.Y);
				_rightClickItem = kryptonListBox1.ListBox.Items[index];
				Console.WriteLine(Resources.right_clicked_on_item_named__ + _rightClickItem);
			}
		}

		private void PauseClick(Object sender, EventArgs e)
		{
			_controller.Pause();
		}

		private void BtnAddClick(Object sender, EventArgs e)
		{
			_controller.AddMessage();
		}

		private void BtnClearClick(Object sender, EventArgs e)
		{
			_controller.Clear(log);
		}

		private void AsyncLogDemoShown(Object sender, EventArgs e)
		{
			_controller.Start(this);
		}

		private void AToolStripMenuItemClick(Object sender, EventArgs e)
		{
			Console.WriteLine(Resources.ClickedA + _rightClickItem);
		}

		private void BToolStripMenuItemClick(Object sender, EventArgs e)
		{
			Console.WriteLine(Resources.ClickedB + _rightClickItem);
		}

		private void CToolStripMenuItemClick(Object sender, EventArgs e)
		{
			Console.WriteLine(Resources.clicked_action_C_on_item__ + _rightClickItem);
		}

		private void BtnSpawnFormsClick(Object sender, EventArgs e)
		{
			for (int i = 0; i < 3; ++i)
			{
				Task.Factory.StartNew(SpawnFormModal);
			}
			for (int i = 0; i < 3; ++i)
			{
				Task.Factory.StartNew(SpawnFormNonModal);
			}
		}

		private void SpawnFormModal()
		{
			using (Closer form = FormFactory.Create<Closer>())
			{
				FormFactory.ShowDialog(this, form);
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
		private void SpawnFormNonModal()
		{
			Closer form = FormFactory.Create<Closer>();
			FormFactory.Show(this, form);
		}

		private void AsyncLogDemoLoad(Object sender, EventArgs e)
		{
			FormFactory.Bind(this);
		}

		private void BuildSparklineClick(Object sender, EventArgs e)
		{
			BuildSparkline();
		}

		private void BuildSparkline()
		{
			List<int?> values = log.Lines.Select(s => String.IsNullOrEmpty(s) ? 0 : s.Length).Select(dummy => (int?)dummy).ToList();
			spark.DataSource = values;
		}

		private void WriteLogEntry(LogEntry entry)
		{
			log.AppendText(entry.ToString());
			NativeMethods.SendMessageScrollToBottom(log.Handle);
		}
	}
}